package com.cruise.game.service.impl.admin;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cruise.game.common.api.ApiException;
import com.cruise.game.mapper.TransactionMapper;
import com.cruise.game.mapper.UserMapper;
import com.cruise.game.mapper.WithdrawalApplicationMapper;
import com.cruise.game.model.entity.Transaction;
import com.cruise.game.model.entity.User;
import com.cruise.game.model.entity.WithdrawalApplication;
import com.cruise.game.model.vo.common.PageResult;
import com.cruise.game.model.vo.user.WithdrawalDetailVO;
import com.cruise.game.model.vo.user.WithdrawalVO;
import com.cruise.game.service.admin.AdminWithdrawalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 管理员提现服务实现
 *
 * @author cruise
 * @date 2025-02-28
 */
@Slf4j
@Service
public class AdminWithdrawalServiceImpl implements AdminWithdrawalService {

    @Resource
    private WithdrawalApplicationMapper withdrawalApplicationMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private TransactionMapper transactionMapper;

    @Override
    public PageResult<WithdrawalVO> getWithdrawalList(String status, LocalDate startDate, LocalDate endDate,
            Integer page, Integer pageSize) {
        // 构建查询条件
        LambdaQueryWrapper<WithdrawalApplication> queryWrapper = new LambdaQueryWrapper<>();

        // 状态查询
        if (StringUtils.isNotBlank(status)) {
            queryWrapper.eq(WithdrawalApplication::getStatus, status);
        }

        // 时间范围查询
        if (startDate != null) {
            queryWrapper.ge(WithdrawalApplication::getCreatedAt, startDate.atStartOfDay());
        }
        if (endDate != null) {
            queryWrapper.le(WithdrawalApplication::getCreatedAt, endDate.atTime(LocalTime.MAX));
        }

        // 排序
        queryWrapper.orderByDesc(WithdrawalApplication::getCreatedAt);

        // 分页查询
        IPage<WithdrawalApplication> withdrawalPage = withdrawalApplicationMapper.selectPage(
                new Page<>(page, pageSize),
                queryWrapper);

        // 转换为VO
        List<WithdrawalVO> withdrawalVOs = new ArrayList<>();
        for (WithdrawalApplication withdrawal : withdrawalPage.getRecords()) {
            WithdrawalVO vo = new WithdrawalVO();
            BeanUtils.copyProperties(withdrawal, vo);
            withdrawalVOs.add(vo);
        }

        // 构建分页结果
        return PageResult.of(withdrawalVOs, withdrawalPage.getTotal(), page, pageSize);
    }

    @Override
    public WithdrawalDetailVO getWithdrawalDetail(Long withdrawalId) {
        // 查询提现申请
        WithdrawalApplication withdrawal = withdrawalApplicationMapper.selectById(withdrawalId);
        if (withdrawal == null) {
            throw new ApiException("提现申请不存在");
        }

        // 查询用户信息
        User user = userMapper.selectById(withdrawal.getUserId());
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 构建提现详情VO
        WithdrawalDetailVO detailVO = new WithdrawalDetailVO();
        BeanUtils.copyProperties(withdrawal, detailVO);

        // 设置用户信息
        WithdrawalDetailVO.UserInfo userInfo = new WithdrawalDetailVO.UserInfo();
        userInfo.setId(user.getId());
        userInfo.setNickname(user.getNickname());
        userInfo.setPhone(user.getPhone());
        userInfo.setWechatId(user.getWechatId());
        detailVO.setUser(userInfo);

        return detailVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processWithdrawal(Long withdrawalId, Boolean approved, String remark) {
        // 查询提现申请
        WithdrawalApplication withdrawal = withdrawalApplicationMapper.selectById(withdrawalId);
        if (withdrawal == null) {
            throw new ApiException("提现申请不存在");
        }

        // 验证状态
        if (!"pending".equals(withdrawal.getStatus())) {
            throw new ApiException("提现申请已处理");
        }

        // 获取用户
        User user = userMapper.selectById(withdrawal.getUserId());
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 更新提现申请状态
        withdrawal.setStatus(approved ? "approved" : "rejected");
        withdrawal.setRemark(remark);
        withdrawal.setUpdatedAt(LocalDateTime.now());

        // 更新提现申请
        boolean success = withdrawalApplicationMapper.updateById(withdrawal) > 0;

        if (success) {
            // 处理交易记录
            Transaction transaction = new Transaction();
            transaction.setUserId(withdrawal.getUserId());
            transaction.setAmount(withdrawal.getAmount());
            transaction.setType("withdrawal");
            transaction.setStatus(approved ? "completed" : "failed");
            transaction.setCreatedAt(LocalDateTime.now());
            transaction.setUpdatedAt(LocalDateTime.now());
            transactionMapper.insert(transaction);

            // 如果拒绝，退还用户余额
            if (!approved) {
                userMapper.updateBalance(withdrawal.getUserId(), withdrawal.getAmount());
            }
        }

        return success;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchProcessWithdrawal(String withdrawalIds, Boolean approved, String remark) {
        if (StringUtils.isBlank(withdrawalIds)) {
            throw new ApiException("提现申请ID不能为空");
        }

        // 解析ID列表
        List<Long> idList = Arrays.stream(withdrawalIds.split(","))
                .map(String::trim)
                .filter(StringUtils::isNotBlank)
                .map(Long::parseLong)
                .collect(Collectors.toList());

        if (idList.isEmpty()) {
            throw new ApiException("提现申请ID不能为空");
        }

        // 处理结果统计
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<Map<String, Object>> failDetails = new ArrayList<>();

        // 批量处理
        for (Long withdrawalId : idList) {
            try {
                boolean success = processWithdrawal(withdrawalId, approved, remark);
                if (success) {
                    successCount++;
                } else {
                    failCount++;
                    Map<String, Object> failDetail = new HashMap<>();
                    failDetail.put("id", withdrawalId);
                    failDetail.put("errorMessage", "处理失败");
                    failDetails.add(failDetail);
                }
            } catch (Exception e) {
                log.error("处理提现申请失败: {}, error: {}", withdrawalId, e.getMessage(), e);
                failCount++;
                Map<String, Object> failDetail = new HashMap<>();
                failDetail.put("id", withdrawalId);
                failDetail.put("errorMessage", e.getMessage());
                failDetails.add(failDetail);
            }
        }

        // 设置处理结果
        result.put("total", idList.size());
        result.put("successCount", successCount);
        result.put("failCount", failCount);
        result.put("failDetails", failDetails);

        // 如果全部失败，抛出异常，这样会触发全局异常处理器并返回错误状态码
        if (successCount == 0 && failCount > 0) {
            throw new ApiException("批量处理提现申请全部失败，请查看详细信息");
        }

        return result;
    }

    @Override
    public Map<String, Object> getTodayWithdrawalStatistics() {
        Map<String, Object> statistics = new HashMap<>();

        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = LocalDate.now().atTime(LocalTime.MAX);

        // 今日提现申请数
        int todayWithdrawals = withdrawalApplicationMapper.countByTimeRange(todayStart, todayEnd);
        statistics.put("todayWithdrawals", todayWithdrawals);

        // 今日提现总金额
        BigDecimal todayWithdrawalAmount = withdrawalApplicationMapper.sumAmountByTimeRange(todayStart, todayEnd);
        statistics.put("todayWithdrawalAmount",
                todayWithdrawalAmount != null ? todayWithdrawalAmount : BigDecimal.ZERO);

        // 待处理提现数
        int pendingWithdrawals = withdrawalApplicationMapper.countByStatus("pending");
        statistics.put("pendingWithdrawals", pendingWithdrawals);

        // 今日已批准提现数
        int todayApprovedWithdrawals = withdrawalApplicationMapper.countByStatusAndTimeRange("approved", todayStart,
                todayEnd);
        statistics.put("todayApprovedWithdrawals", todayApprovedWithdrawals);

        // 今日已拒绝提现数
        int todayRejectedWithdrawals = withdrawalApplicationMapper.countByStatusAndTimeRange("rejected", todayStart,
                todayEnd);
        statistics.put("todayRejectedWithdrawals", todayRejectedWithdrawals);

        return statistics;
    }
}